package com.s7.widget.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.TypedValue;

import com.s7.widget.R;


/**
 * 自定义ImageView
 * 可显示为圆形、方形; 可设置 圆角、边框
 */
public class RoundImageView extends AppCompatImageView {

    /**
     * 图片的类型，圆形or方形
     */
    private boolean isOval;

    /**
     * 描边的颜色、宽度
     */
    private int mBorderColor;
    private float mBorderWidth = 0.0f;
    /**
     * 圆角的大小
     */
    private float mCornerRadius = 0.0f;

    /**
     * 圆角大小
     * 左上角、右上角、左下角、右下角
     */
    private float mLeftTopRadius = 0.0f;
    private float mRightTopRadius = 0.0f;
    private float mLeftBottomRadius = 0.0f;
    private float mRightBottomRadius = 0.0f;

    /**
     * 绘图的Paint
     */
    private Paint mBitmapPaint;

    /**
     * 边框的Paint
     */
    private Paint mBorderPaint;

    /**
     * 圆/椭圆 的半径
     */
    private float mRadius;

    /**
     * 遮罩颜色
     */
    private int mMaskColor;

    /**
     * 遮罩的Paint
     */
    private Paint mMaskPaint;

    /**
     * 3x3 矩阵，主要用于缩小放大
     */
    private Matrix mMatrix;
    /**
     * 渲染图像，使用图像为绘制图形着色
     */
    private BitmapShader mBitmapShader;

    /**
     * view的宽度、高度
     */
    private int mWidth, mHeight;

    /**
     * 圆角图片区域
     */
    private RectF mRoundRect;
    private Path mRoundPath;

    public RoundImageView(Context context) {
        this(context, null);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView, defStyleAttr, 0);

        isOval = a.getBoolean(R.styleable.RoundImageView_roundOval, false);
        mBorderColor = a.getColor(R.styleable.RoundImageView_roundBorderColor, Color.WHITE);
        mBorderWidth = a.getDimension(R.styleable.RoundImageView_roundBorderWidth, 0.0f);
        mCornerRadius = a.getDimension(R.styleable.RoundImageView_roundCornerRadius, 0.0f);
        mLeftTopRadius = a.getDimension(R.styleable.RoundImageView_roundLeftTopCornerRadius, 0.0f);
        mRightTopRadius = a.getDimension(R.styleable.RoundImageView_roundRightTopCornerRadius, 0.0f);
        mLeftBottomRadius = a.getDimension(R.styleable.RoundImageView_roundLeftBottomCornerRadius, 0.0f);
        mRightBottomRadius = a.getDimension(R.styleable.RoundImageView_roundRightBottomCornerRadius, 0.0f);
        mMaskColor = a.getColor( R.styleable.RoundImageView_roundMaskColor, Color.TRANSPARENT);
        a.recycle();
        init();

    }

    private void init() {
        mRoundPath = new Path();
        mMatrix = new Matrix();
        mBitmapPaint = new Paint();
        mBitmapPaint.setAntiAlias(true);
        mBorderPaint = new Paint();
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setStrokeCap(Paint.Cap.ROUND);
        mMaskPaint = new Paint();
        mMaskPaint.setAntiAlias(true);
        mMaskPaint.setStyle(Paint.Style.FILL);
        mMaskPaint.setXfermode(null);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mWidth = widthMeasureSpec;
        mHeight = heightMeasureSpec;

        /**
         * 如果类型是圆形，则强制以小值为准
         */
        if (isOval) {
            mRadius = Math.min(MeasureSpec.getSize(mWidth),
                    MeasureSpec.getSize(mHeight)) / 2 - mBorderWidth / 2;
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        /**
         * 椭圆/方形 图片的范围
         */
        if (!(isOval && w == h)) {
            mRoundRect = new RectF(mBorderWidth / 2, mBorderWidth / 2,
                    w - mBorderWidth / 2, h - mBorderWidth / 2);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        /**
         * 边框
         */
        mBorderPaint.setColor(mBorderColor);
        mBorderPaint.setStrokeWidth(mBorderWidth);

        /**
         * 遮罩
         */
        mMaskPaint.setColor(mMaskColor);

        if (getDrawable() == null) {
            return;
        }
        setUpShader();

        if (isOval) {
            if (getWidth() == getHeight()) {
                canvas.drawCircle(mRadius + mBorderWidth / 2, mRadius + mBorderWidth / 2, mRadius, mBitmapPaint);
                // 绘制遮罩
                if (mMaskColor != Color.TRANSPARENT) {
                    canvas.drawCircle(mRadius + mBorderWidth / 2, mRadius + mBorderWidth / 2, mRadius, mMaskPaint);
                }
                //绘制描边
                canvas.drawCircle(mRadius + mBorderWidth / 2, mRadius + mBorderWidth / 2, mRadius, mBorderPaint);

            } else {
                canvas.drawOval(mRoundRect, mBitmapPaint);
                // 绘制遮罩
                if (mMaskColor != Color.TRANSPARENT) {
                    canvas.drawOval(mRoundRect, mMaskPaint);
                }
                //绘制描边
                canvas.drawOval(mRoundRect, mBorderPaint);
            }
        } else {
            setRoundPath();
            canvas.drawPath(mRoundPath, mBitmapPaint);
            // 绘制遮罩
            if (mMaskColor != Color.TRANSPARENT) {
                canvas.drawPath(mRoundPath, mMaskPaint);
            }
            //绘制描边
            canvas.drawPath(mRoundPath, mBorderPaint);
        }
    }


    private void setRoundPath() {
        mRoundPath.reset();

        /**
         * mCornerRadius 优先级 > mLeftTopRadius/mRightTopRadius/mRightBottomRadius/mLeftBottomRadius
         */
        if (mCornerRadius > 0) {
            mRoundPath.addRoundRect(mRoundRect,
                    new float[]{mCornerRadius, mCornerRadius,
                            mCornerRadius, mCornerRadius,
                            mCornerRadius, mCornerRadius,
                            mCornerRadius, mCornerRadius},
                    Path.Direction.CW);
        } else {
            mRoundPath.addRoundRect(mRoundRect,
                    new float[]{mLeftTopRadius, mLeftTopRadius,
                            mRightTopRadius, mRightTopRadius,
                            mRightBottomRadius, mRightBottomRadius,
                            mLeftBottomRadius, mLeftBottomRadius},
                    Path.Direction.CW);
        }

    }


    /**
     * 初始化BitmapShader
     */
    private void setUpShader() {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            return;
        }

        Bitmap bmp = drawableToBitamp(drawable);
        // 将bmp作为着色器，就是在指定区域内绘制bmp
        mBitmapShader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        float scale = 1.0f;

        if (!(bmp.getWidth() == getWidth() && bmp.getHeight() == getHeight())) {
            // 如果图片的宽或者高与view的宽高不匹配，计算出需要缩放的比例；
            // 缩放后的图片的宽高，一定要大于我们view的宽高；所以我们这里取大值；
            scale = Math.max(getWidth() * 1.0f / bmp.getWidth(),
                    getHeight() * 1.0f / bmp.getHeight());
            //使缩放后的图片居中
            float dx = (scale * bmp.getWidth() - getWidth()) / 2;
            float dy = (scale * bmp.getHeight() - getHeight()) / 2;
            mMatrix.setTranslate(-dx, -dy);
        }
        // shader的变换矩阵，我们这里主要用于放大或者缩小
        mMatrix.preScale(scale, scale);
        mBitmapShader.setLocalMatrix(mMatrix);

        // 设置变换矩阵
        mBitmapShader.setLocalMatrix(mMatrix);
        // 设置shader
        mBitmapPaint.setShader(mBitmapShader);
    }


    /**
     * drawable转bitmap
     */
    private Bitmap drawableToBitamp(Drawable drawable) {
        try {
            Bitmap bitmap;
            if (drawable instanceof BitmapDrawable) {
                BitmapDrawable bd = (BitmapDrawable) drawable;
                return bd.getBitmap();
            }
            int w = drawable.getIntrinsicWidth();
            int h = drawable.getIntrinsicHeight();
            bitmap = Bitmap.createBitmap(w, h, drawable.getOpacity() != PixelFormat.OPAQUE
                    ? Bitmap.Config.ARGB_4444 : Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, w, h);
            drawable.draw(canvas);
            return bitmap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 设置图片类型
     * @param oval true 圆形; false 方形
     */
    public RoundImageView setOval(boolean oval) {
        if (this.isOval != oval) {
            this.isOval = oval;
            requestLayout();
        }
        return this;
    }


    /**
     * 设置圆角图片的圆角大小
     * @param cornerRadius
     */
    public RoundImageView setCornerRadius(int cornerRadius) {
        cornerRadius = dp2px(cornerRadius);
        if (mCornerRadius != cornerRadius) {
            mCornerRadius = cornerRadius;
            invalidate();
        }
        return this;
    }

    /**
     * 设置圆角图片的圆角大小
     * @param mLeftTopRadius 左上圆角大小
     * @param mRightTopRadius 右上圆角大小
     * @param mLeftBottomRadius 左下圆角大小
     * @param mRightBottomRadius 右下圆角大小
     * @return
     */
    public RoundImageView setCornerRadius(int mLeftTopRadius, int mRightTopRadius,
                                          int mLeftBottomRadius, int mRightBottomRadius) {
        if (this.mLeftTopRadius != dp2px(mLeftTopRadius) || this.mRightTopRadius != dp2px(mRightTopRadius)
                || this.mLeftBottomRadius != dp2px(mLeftBottomRadius)
                || this.mRightBottomRadius != dp2px(mRightBottomRadius)) {
            this.mLeftTopRadius = dp2px(mLeftTopRadius);
            this.mRightTopRadius = dp2px(mRightTopRadius);
            this.mLeftBottomRadius = dp2px(mLeftBottomRadius);
            this.mRightBottomRadius = dp2px(mRightBottomRadius);
            invalidate();
        }
        return this;
    }


    /**
     * 设置描边宽度
     */
    public RoundImageView setBorderWidth(int borderWidth) {
        borderWidth = dp2px(borderWidth);
        if (mBorderWidth != borderWidth) {
            mBorderWidth = borderWidth;
            invalidate();
        }
        return this;
    }

    /**
     * 设置描边颜色
     */
    public RoundImageView setBorderColor(int borderColor) {
        if (mBorderColor != borderColor) {
            mBorderColor = borderColor;
            invalidate();
        }
        return this;
    }

    /**
     * 设置遮罩样式
     */
    public RoundImageView setMaskColor(int mMaskColor) {
        if (mMaskColor != mMaskColor) {
            mBorderColor = mMaskColor;
            invalidate();
        }
        return this;
    }

    private int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

}